package services

import (
	"TaskAssignmentSystem/internal/admin/dao"
	"TaskAssignmentSystem/pkg/timehandler"
	"TaskAssignmentSystem/pkg/utils"
	"errors"
	"fmt"
	"strings"
	"time"
)

type UserBalanceLogService struct {
}

const (
	BalanceLogLogTypeIn              = 1
	BalanceLogLogTypeOut             = 2
	BalanceLogBusinessTypeCash       = 1
	BalanceLogBusinessTypeProduct    = 2
	BalanceLogBusinessTypeSalary     = 3
	BalanceLogBusinessTypeCreateTeam = 6
)

type HistoryBalanceResponse struct {
	Balance float64 `json:"balance"` //芝草数量
}

// 兑换现金，兑换商品，扣除芝草Log
func (u *UserBalanceLogService) AddConsumptionLog(orderId, remark string) error {
	return u.AddOrderLog(orderId, remark, BalanceLogLogTypeOut)
}

// 兑换现金，兑换商品失败，返还芝草Log
func (u *UserBalanceLogService) AddIncomeLog(orderId, remark string) error {
	return u.AddOrderLog(orderId, remark, BalanceLogLogTypeIn)
}

// 兑换现金，兑换商品，添加Log
func (u *UserBalanceLogService) AddOrderLog(orderId, remark string, logType int) error {
	var orderService SystemOrderService
	//查询订单
	order, err := orderService.OrderInfo(orderId)
	if err != nil {
		return err
	}
	//查用户
	var userService UserService
	exist, user, err := userService.VerifyAndQueryUserByUserId(order.UserId)
	if err != nil {
		return err
	}
	if !exist {
		return errors.New("该用户不存在")
	}
	var log dao.SystemUserBalanceLog
	log.OrderId = orderId
	log.UserId = user.UserId
	log.TeamNumber = user.TeamNumber
	log.Amount = order.Balance
	log.LogType = logType
	if order.OrderType == OrderTypeCash {
		log.BusinessType = BalanceLogBusinessTypeCash
	} else if order.OrderType == OrderTypeProduct {
		log.BusinessType = BalanceLogBusinessTypeProduct
	} else {
		return errors.New("订单类型异常")
	}
	log.Remark = remark
	log.ReadStatus = 0
	// 发系统消息
	/*var msg dao.Common[dao.UserMsgInfo]
	userMsgInfo := dao.UserMsgInfo{}
	userMsgInfo.SystemUserId = user.UserId
	userMsgInfo.Type = 2
	msg.CreateOne(userMsgInfo)*/

	var commonDao dao.Common[dao.SystemUserBalanceLog]
	return commonDao.CreateOne(log).Error
}

// 发放工资Log
func (u *UserBalanceLogService) AddPayWagesLog(userId, remark, url string, balance float64, businessType int) error {
	var salaryService SalaryService
	var commonDao dao.Common[dao.SystemUserBalanceLog]
	var msg dao.Common[dao.UserMsgInfo]
	if user, err := salaryService.GetViewUserOne(userId); err == nil {
		salaryService.AddBalance(user, balance)
		//发消息
		userMsgInfo := dao.UserMsgInfo{}
		userMsgInfo.SystemUserId = userId
		userMsgInfo.Type = 1
		msg.CreateOne(userMsgInfo)
		//记发放记录
		user.Balance = user.Balance + balance
		var log dao.SystemUserBalanceLog
		log.UserId = user.UserId
		log.TeamNumber = user.TeamNumber
		log.RemainAmount = user.Balance
		log.Amount = balance
		log.LogType = 1
		log.BusinessType = businessType
		if businessType == 3 && remark == "" {
			remark = "芝草发放"
		} else if businessType == 4 && remark == "" {
			remark = "团长提成发放"
		}
		log.Remark = remark
		log.Url = url
		//log.Remark = remark + fmt.Sprintf("[%.2f]", balance)
		return commonDao.CreateOne(log).Error
	} else {
		return err
	}
}

// 工资退回
func (u *UserBalanceLogService) RetrunPayWagesLog(userId, remark string, balance float64, businessType int) error {
	var salaryService SalaryService
	var commonDao dao.Common[dao.SystemUserBalanceLog]
	if user, err := salaryService.GetViewUserOne(userId); err == nil {
		salaryService.DelBalance(userId, balance)
		user.Balance = user.Balance - balance
		var log dao.SystemUserBalanceLog
		log.UserId = user.UserId
		log.TeamNumber = user.TeamNumber
		log.RemainAmount = user.Balance
		log.Amount = balance
		log.LogType = 1
		log.BusinessType = 5
		if businessType == 3 && remark == "" {
			remark = "收入撤回，详情请联系平台运营"
		} else if businessType == 4 && remark == "" {
			remark = "团长提成撤回"
		}
		log.Remark = remark
		log.Url = user.DetailUrl
		//log.Remark = remark + fmt.Sprintf("[%.2f]", balance)
		return commonDao.CreateOne(log).Error
	} else {
		return err
	}
}

func (u *UserBalanceLogService) GetHistoryBalance(userId string) (float64, error) {
	var commonDao dao.Common[HistoryBalanceResponse]
	sql := fmt.Sprintf(
		"SELECT IFNULL(SUM(IFNULL(amount,0)),0) AS balance FROM tas_system_user_balance_log WHERE log_type = %d AND business_type in %v AND user_id = '%s'",
		BalanceLogLogTypeIn, "(3,4)", userId)
	if data, err := commonDao.RawOne(sql); err != nil {
		return 0, err
	} else {
		sqlOut := fmt.Sprintf(
			"SELECT IFNULL(SUM(IFNULL(amount,0)),0) AS balance FROM tas_system_user_balance_log WHERE log_type = %d AND business_type = %d AND user_id = '%s'",
			BalanceLogLogTypeIn, 5, userId)
		if dataOut, err := commonDao.RawOne(sqlOut); err != nil {
			return 0, err
		} else {
			data.Balance = data.Balance - dataOut.Balance
			return data.Balance, nil
		}
	}
}

func (u *UserBalanceLogService) GetHistoryOutBalance(userId string) (float64, error) {
	var commonDao dao.Common[HistoryBalanceResponse]
	//历史总支出
	historyOutAmountSql := fmt.Sprintf(" IFNULL((SELECT IFNULL(SUM(IFNULL(amount,0)),0) AS balance FROM tas_system_user_balance_log WHERE log_type = %d AND user_id = '%s'),0) ", BalanceLogLogTypeOut, userId)
	//历史支出返还
	historyOutBackAmountSql := fmt.Sprintf(" IFNULL((SELECT IFNULL(SUM(IFNULL(amount,0)),0) AS balance FROM tas_system_user_balance_log WHERE log_type = %d AND business_type IN (%d, %d) AND user_id = '%s'),0) ", BalanceLogLogTypeIn, BalanceLogBusinessTypeCash, BalanceLogBusinessTypeProduct, userId)
	//历史支出 = 历史总支出 - 历史支出返还
	sql := fmt.Sprintf("SELECT ( %s - %s ) AS balance", historyOutAmountSql, historyOutBackAmountSql)
	if data, err := commonDao.RawOne(sql); err != nil {
		return 0, err
	} else {
		return data.Balance, nil
	}
}

func (u *UserBalanceLogService) GetMonthCashOutBalance(userId string) (float64, error) {
	//当月现金兑换成功统计（审核通过的）
	whereSql := fmt.Sprintf(
		" WHERE o.order_type = 1 AND o.user_id = '%s' AND substring(o.created_at, 1, 7) = substring(NOW(), 1, 7) AND r.`status` = %d ",
		userId,
		OrderReviewRecordTypePass,
	)
	monthCashOutAmountSql := fmt.Sprintf(
		" %s %s %s %s ",
		"SELECT IFNULL(SUM(o.balance), 0) AS balance FROM tas_system_order o",
		"LEFT JOIN tas_system_order_review_record r ON o.order_id = r.order_id",
		"LEFT JOIN tas_system_user_balance_log l ON o.order_id = l.order_id",
		whereSql,
	)
	var commonDao dao.Common[HistoryBalanceResponse]
	if data, err := commonDao.RawOne(monthCashOutAmountSql); err != nil {
		return 0, err
	} else {
		return data.Balance, nil
	}
}

type UserBalanceIncomesResponse struct {
	Id           uint   `json:"id"`
	Title        string `json:"title"`         //标题
	Desc         string `json:"desc"`          //说明
	Time         string `json:"time"`          //时间
	BusinessType int    `json:"business_type"` //业务类型，1：现金兑换，2：商品兑换，3：工资发放，4：团长提成，5：工资撤回
	ReadStatus   int    `json:"read_status"`   //已读状态(0-未读,1-已读)
	Url          string `json:"url"`           //超链接地址
}

func (u *UserBalanceLogService) UserBalanceIncomes(sysUserId uint, page, pageSize int64) (int64, []UserBalanceIncomesResponse, error) {
	//查用户
	var userService UserService
	exist, user, err := userService.VerifyAndQueryUser(sysUserId)
	if err != nil {
		return 0, nil, err
	}
	if !exist {
		return 0, nil, errors.New("该用户不存在")
	}
	var commonServe CommonService[dao.SystemUserBalanceLog]
	commonServe.Page = page
	commonServe.PageSize = pageSize
	commonServe.WhereStr = append(commonServe.WhereStr, fmt.Sprintf("log_type = %d", BalanceLogLogTypeIn))
	commonServe.WhereStr = append(commonServe.WhereStr, fmt.Sprintf("user_id = '%v'", user.UserId))
	commonServe.Order = "id desc"
	if res, err := commonServe.SelectList(); err != nil {
		return 0, nil, err
	} else {
		var list []UserBalanceIncomesResponse
		for _, v := range res.Data {
			var item UserBalanceIncomesResponse
			item.Id = v.Id
			item.Title = v.Remark
			item.Desc = fmt.Sprintf("+%s芝草", utils.Float64ToString(v.Amount))
			item.Time = v.CreatedAt.Format(timehandler.FormatLayoutTime)
			item.BusinessType = v.BusinessType
			item.ReadStatus = v.ReadStatus
			item.Url = v.Url
			list = append(list, item)
		}
		return res.Total, list, nil
	}
}

type IncomeRankResponse struct {
	Number   string `json:"number"`    //排名
	NickName string `json:"nick_name"` //昵称
	Des      string `json:"des"`       //说明
	UserId   string `json:"user_id"`   //用户ID
	Avatar   string `json:"avatar"`    //头像
}

func (u *UserBalanceLogService) UserIncomeRank(queryType string, userId uint) (string, string, []IncomeRankResponse, *IncomeRankResponse, error) {
	var startTime string
	var endTime string
	now := time.Now().Format(timehandler.FormatLayoutDate)
	var from, to string
	if queryType == "1" {
		//日榜
		startTime = time.Now().AddDate(0, 0, -1).Format(timehandler.FormatLayoutDate)
		endTime = time.Now().AddDate(0, 0, -1).Format(timehandler.FormatLayoutDate)
		from, to = startTime, endTime
	} else if queryType == "2" {
		//周榜
		//startTime, endTime = utils.GetWeekStartEnd(now)
		weekday := time.Now().Weekday()
		daysAgo := time.Duration((weekday+6)%7) * 24 * time.Hour
		st := time.Now().Add(-daysAgo)
		daysAhead := time.Duration((7-weekday)%7) * 24 * time.Hour
		et := time.Now().Add(daysAhead)
		startTime = st.Format("2006-01-02")
		endTime = et.Format("2006-01-02")
		from, to = startTime, endTime
	} else if queryType == "3" {
		//月榜
		startTime, endTime = utils.GetMonthStartEnd(now)
		from, to = startTime, endTime
	} else {
		//总榜
		startTime = "1900-01-01"
		endTime = "9999-12-31"
		from, to = "-", "-"
	}
	startTime += " 00:00:00"
	endTime += " 23:59:59"
	/*listSql := fmt.Sprintf(
		"SELECT u.avatar,u.user_id,u.nick_name,CONCAT(0 + cast(SUM(IFNULL(l.amount, 0)) AS CHAR),'芝草') AS des FROM tas_system_user_balance_log l LEFT JOIN tas_system_user u ON l.user_id = u.user_id WHERE log_type = %d AND business_type in %v AND l.created_at >= '%s' AND l.created_at <= '%s' GROUP BY l.user_id ORDER BY SUM(IFNULL(l.amount, 0)) DESC ",
		BalanceLogLogTypeIn,
		"(3,4)",
		startTime,
		endTime,
	)*/
	listSql := fmt.Sprintf(
		"SELECT b.avatar,b.user_id,b.nick_name,(b.amount-IFNULL(c.amount,0)) des from ( SELECT u.avatar,u.user_id,u.nick_name,SUM( IFNULL( l.amount, 0 )) amount FROM tas_system_user_balance_log l LEFT JOIN tas_system_user u ON l.user_id = u.user_id WHERE log_type = %d AND business_type in %v AND l.created_at >= '%s' AND l.created_at <= '%s' GROUP BY l.user_id ) b LEFT JOIN (SELECT u.avatar,u.user_id,u.nick_name,SUM( IFNULL( l.amount, 0 )) amount FROM tas_system_user_balance_log l LEFT JOIN tas_system_user u ON l.user_id = u.user_id WHERE log_type = %d AND business_type = %d AND l.created_at >= '%s' AND l.created_at <= '%s' GROUP BY l.user_id ) c on b.user_id = c.user_id ORDER BY des desc ",
		BalanceLogLogTypeIn,
		"(3,4)",
		startTime,
		endTime,
		BalanceLogLogTypeIn,
		5,
		startTime,
		endTime,
	)
	sql := fmt.Sprintf(
		"SELECT (@i := @i + 1) AS number,a.nick_name,a.des,a.user_id,a.avatar FROM(%s) a JOIN (SELECT @i := 0) n limit 50",
		listSql,
	)
	var commonDao dao.Common[IncomeRankResponse]
	if data, err := commonDao.RawList(sql); err != nil {
		return "", "", nil, nil, err
	} else {
		for i, d := range data {
			//data[i].Des = strings.ReplaceAll(d.Des, ".00", "") + "芝草"
			data[i].Des = strings.ReplaceAll(d.Des, ".00", "")
		}

		//查当前用户
		var userDao dao.Common[dao.SystemUser]
		if user, err := userDao.First(map[string]interface{}{"id": userId}); err != nil {
			return "", "", nil, nil, err
		} else {
			flag := false
			userRank := &IncomeRankResponse{}
			for _, income := range data {
				if income.UserId == user.UserId {
					flag = true
					userRank.Number = income.Number
					userRank.UserId = income.UserId
					userRank.NickName = income.NickName
					//userRank.Des = strings.ReplaceAll(income.Des, ".00", "") + "芝草"
					userRank.Des = income.Des
					userRank.Avatar = income.Avatar
					break
				}
			}
			//用户在排行榜前50,则直接返回
			if flag {
				return from, to, data, userRank, nil
			} else {
				//用户不在排行榜前50,则查出来返回
				/*userSql := fmt.Sprintf(
					"SELECT u.avatar,u.user_id,u.nick_name,CONCAT(0 + cast(SUM(IFNULL(l.amount, 0)) AS CHAR),'芝草') AS des FROM tas_system_user_balance_log l LEFT JOIN tas_system_user u ON l.user_id = u.user_id WHERE log_type = %d AND business_type in %v AND l.created_at >= '%s' AND l.created_at <= '%s' AND u.user_id = '%s' GROUP BY l.user_id ORDER BY SUM(IFNULL(l.amount, 0)) DESC ",
					BalanceLogLogTypeIn,
					"(3,4)",
					startTime,
					endTime,
					user.UserId,
				)*/
				userSql := fmt.Sprintf(
					"SELECT b.avatar,b.user_id,b.nick_name,(b.amount-IFNULL(c.amount,0)) des from ( SELECT u.avatar,u.user_id,u.nick_name,SUM( IFNULL( l.amount, 0 )) amount FROM tas_system_user_balance_log l LEFT JOIN tas_system_user u ON l.user_id = u.user_id WHERE log_type = %d AND business_type in %v AND l.created_at >= '%s' AND l.created_at <= '%s' AND u.user_id = '%s' GROUP BY l.user_id ) b LEFT JOIN ( SELECT u.avatar,u.user_id,u.nick_name,SUM( IFNULL( l.amount, 0 )) amount FROM tas_system_user_balance_log l LEFT JOIN tas_system_user u ON l.user_id = u.user_id WHERE log_type = %d AND business_type = %d AND l.created_at >= '%s' AND l.created_at <= '%s' AND u.user_id = '%s' GROUP BY l.user_id ) c on b.user_id = c.user_id ORDER BY des desc ",
					BalanceLogLogTypeIn,
					"(3,4)",
					startTime,
					endTime,
					user.UserId,
					BalanceLogLogTypeIn,
					5,
					startTime,
					endTime,
					user.UserId,
				)
				if userRank, err := commonDao.RawOne(userSql); err != nil {
					return "", "", nil, nil, err
				} else {
					//userRank.Des = strings.ReplaceAll(userRank.Des, ".00", "") + "芝草"
					userRank.Des = strings.ReplaceAll(userRank.Des, ".00", "")
					return from, to, data, &userRank, nil
				}
			}
		}
		return from, to, data, nil, nil
	}
}

type TeamIncomeRankResponse struct {
	Number       string `json:"number"`         //排名
	TeamNumber   string `json:"team_number"`    //团队编号
	Des          string `json:"des"`            //说明
	Avatar       string `json:"avatar"`         //头像
	TeamNickName string `json:"team_nick_name"` //团长昵称
}

func (u *UserBalanceLogService) TeamIncomeRank(queryType string) (string, string, []TeamIncomeRankResponse, error) {
	var startTime string
	var endTime string
	//now := time.Now().Format(timehandler.FormatLayoutDate)
	now := time.Now().AddDate(0, 0, -1).Format(timehandler.FormatLayoutDate)
	var from, to string
	if queryType == "1" {
		//日榜
		startTime = now
		endTime = now
		from, to = now, now
	} else if queryType == "2" {
		//周榜
		/*startTime, endTime = utils.GetWeekStartEnd(now)
		from, to = startTime, endTime*/
		weekday := time.Now().Weekday()
		daysAgo := time.Duration((weekday+6)%7) * 24 * time.Hour
		st := time.Now().Add(-daysAgo)
		daysAhead := time.Duration((7-weekday)%7) * 24 * time.Hour
		et := time.Now().Add(daysAhead)
		startTime = st.Format("2006-01-02")
		endTime = et.Format("2006-01-02")
		from, to = startTime, endTime
	} else if queryType == "3" {
		//月榜
		startTime, endTime = utils.GetMonthStartEnd(now)
		from, to = startTime, endTime
	} else {
		//总榜
		startTime = "1900-01-01"
		endTime = "9999-12-31"
		from, to = "-", "-"
	}
	startTime += " 00:00:00"
	endTime += " 23:59:59"
	/*listSql := fmt.Sprintf(
		"SELECT u.nick_name team_nick_name,u.team_number,u.avatar,CONCAT(0 + cast(SUM(IFNULL(l.amount, 0)) AS CHAR),'芝草') AS des FROM tas_system_user_balance_log l LEFT JOIN tas_system_user u ON l.user_id = u.user_id WHERE log_type = %d AND business_type = %d AND l.created_at >= '%s' AND l.created_at <= '%s' GROUP BY l.team_number ORDER BY SUM(IFNULL(l.amount, 0)) DESC ",
		BalanceLogLogTypeIn,
		BalanceLogBusinessTypeSalary,
		startTime,
		endTime,
	)
	sql := fmt.Sprintf(
		"SELECT (@i := @i + 1) AS number,a.team_number,a.des,a.avatar,a.team_nick_name FROM(%s) a JOIN (SELECT @i := 0) n limit 50",
		listSql,
	)*/
	/*sql := fmt.Sprintf(
		"SELECT b.nick_name team_nick_name,a.team_number,b.avatar,CONCAT(IFNULL(c.amount,0),'芝草') des from tas_system_team a LEFT JOIN tas_system_user b on a.user_id = b.user_id LEFT JOIN (SELECT team_number,sum(amount) amount FROM tas_system_user_balance_log WHERE log_type = %d AND business_type = %d AND created_at >= '%s' AND created_at <= '%s' AND team_number in (select team_number from tas_system_team) GROUP BY team_number) c on a.team_number = c.team_number WHERE c.amount > 0 ORDER BY c.amount desc",
		BalanceLogLogTypeIn,
		BalanceLogBusinessTypeSalary,
		startTime,
		endTime,
	)*/
	sql := fmt.Sprintf(
		"SELECT b.team_nick_name,b.team_number,b.avatar,(b.amount-IFNULL(c.amount,0)) des FROM ( SELECT b.nick_name team_nick_name,a.team_number,b.avatar,IFNULL( c.amount, 0 ) amount from tas_system_team a LEFT JOIN tas_system_user b on a.user_id = b.user_id LEFT JOIN (SELECT team_number,sum(amount) amount FROM tas_system_user_balance_log WHERE log_type = %d AND business_type = %d AND created_at >= '%s' AND created_at <= '%s' AND team_number in (select team_number from tas_system_team) GROUP BY team_number) c on a.team_number = c.team_number WHERE c.amount > 0 ) b LEFT JOIN ( SELECT b.nick_name team_nick_name,a.team_number,b.avatar,IFNULL( c.amount, 0 ) amount from tas_system_team a LEFT JOIN tas_system_user b on a.user_id = b.user_id LEFT JOIN (SELECT team_number,sum(amount) amount FROM tas_system_user_balance_log WHERE log_type = %d AND business_type = %d AND created_at >= '%s' AND created_at <= '%s' AND team_number in (select team_number from tas_system_team) GROUP BY team_number) c on a.team_number = c.team_number WHERE c.amount > 0 ) c on b.team_number = c.team_number WHERE b.team_number != 'zxz' ORDER BY des desc",
		BalanceLogLogTypeIn,
		BalanceLogBusinessTypeSalary,
		startTime,
		endTime,
		BalanceLogLogTypeIn,
		5,
		startTime,
		endTime,
	)
	var commonDao dao.Common[TeamIncomeRankResponse]
	if data, err := commonDao.RawList(sql); err != nil {
		return "", "", nil, err
	} else {
		for i, _ := range data {
			//data[i].Des = d.Des + "芝草"
			data[i].Number = utils.IntToString(i + 1)
		}
		return from, to, data, nil
	}
}

type UserBalanceDetailResponse struct {
	Balance         string `json:"balance"`
	ThisMonthAmount string `json:"this_month_amount"`
	HistoryPay      string `json:"history_pay"`
	HistoryIncome   string `json:"history_income"`
}

func (u *UserBalanceLogService) QueryUserBalanceDetail(userId string) (*UserBalanceDetailResponse, error) {
	var commonServe dao.Common[UserBalanceDetailResponse]
	sql := fmt.Sprintf("SELECT a.balance,b.amount this_month_amount,c.amount history_pay,d.amount history_income from tas_system_user a ")
	sql += fmt.Sprintf("LEFT JOIN (SELECT sum(amount) amount,user_id FROM tas_system_user_balance_log WHERE user_id = '%v' and log_type = 2 and LEFT(created_at,7) = DATE_FORMAT(NOW(), '%%Y-%%m')) b on a.user_id = b.user_id ", userId)
	sql += fmt.Sprintf("LEFT JOIN (SELECT sum(amount) amount,user_id FROM tas_system_user_balance_log WHERE user_id = '%v' and log_type = 2) c on a.user_id = c.user_id ", userId)
	sql += fmt.Sprintf("LEFT JOIN (SELECT sum(amount) amount,user_id FROM tas_system_user_balance_log WHERE user_id = '%v' and log_type = 1) d on a.user_id = d.user_id ", userId)
	sql += fmt.Sprintf("WHERE a.user_id = '%v'", userId)
	if team, err := commonServe.RawOne(sql); err != nil {
		return nil, err
	} else {
		return &team, nil
	}
}
